#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <sys/types.h>  /* See NOTES */
#include <netinet/ip.h> /* superset of previous */
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include "cJSON.h"
#include "shmem.h"
#include "msg_queue_peer.h"
#define N 1024

#define shmemname "shmem"

union val_t {

    int bool;
    int a;
    float b;
};

struct std_node
{
    int key;
    int type;
    int type_dev;
    union val_t old_val;
    union val_t new_val;
    int ret;
};
struct msgqueue
{
    int typekey;
    char data[64];
};

void *func2(void *arg)
{
    char buf[N] = {0};
    char buf1[32] ="light";
    int clifd = *((int *)arg);
    struct msgqueue readque;
    while (1)
    {
        msg_queue_recv("msgqueue", &readque, sizeof(struct msgqueue), 301, 0);
        printf("%d  %s\n", readque.typekey, readque.data);
        if (readque.typekey == 301)
        {
            cJSON *root = cJSON_CreateObject();
            cJSON_AddItemToObject(root, "dev", cJSON_CreateString(buf1));
            cJSON_AddItemToObject(root, "val", cJSON_CreateString(readque.data));

            char *p = cJSON_Print(root);
            send(clifd, p, strlen(p), 0);
            printf("%s\n", p);
            free(p);
            cJSON_Delete(root);
        }
    }
}

void *func(void *arg)
{
    char buf[N] = {0};
    // int *p = (int *)arg;
    // int clifd = *p;

    int clifd = *((int *)arg);
    while (1)
    {
        //接收客户端的消息，如果客户端退出的话，服务器也退出
        //接收服务器的消息
        bzero(buf, N);
        int len = recv(clifd, buf, N, 0);
        cJSON *root = cJSON_Parse(buf);
        if (len < 0)
        {
            perror("recv err\n");
            break;
        }
        else if (len == 0)
        {
            printf("client exit\n");
            break;
        }
        else
        {

            struct shm_param shmpam;
            if (shm_init(&shmpam, shmemname, 1024) < 0)
            {
                printf("shm init err\n");
                return NULL;
            }

            int *num = shm_getaddr(&shmpam);
            //*num = 3;

            // cJSON *stm32 = cJSON_GetObjectItem(root, "stm32");
            cJSON *data = cJSON_GetObjectItem(root, "data");
            struct std_node *ptr = (struct std_node *)(num + 1);
            struct std_node *ptr1 = (struct std_node *)(num + 1);
            //获取数组中每一组节点地址
            for (int i = 0; i < cJSON_GetArraySize(data); i++)
            {
                ptr=ptr1;
                cJSON *item = cJSON_GetArrayItem(data, i);
                cJSON *key = cJSON_GetObjectItem(item, "key");
                cJSON *val1 = cJSON_GetObjectItem(item, "val");
                printf("%s:%d\n", key->string, key->valueint);
        
                for (int i = 0; i < *num; i++)
                {
                    //printf("%d\n",*num);
                    if (ptr->key == key->valueint)
                    {
                        if (ptr->type == 1)
                        {
                            ptr->old_val.bool = ptr->new_val.bool;
                            ptr->new_val.bool = val1->valueint;
                        }
                        else if (ptr ->type == 2)
                        {
                             ptr->old_val.a = ptr->new_val.a;
                            ptr ->new_val.a = val1->valueint;
                        }
                        else if (ptr ->type == 3)
                        {
                             ptr->old_val.b = ptr->new_val.b;
                            ptr ->new_val.b = val1->valuedouble;
                        }            
                    }
                    ptr++;
                }

            }
        }
    }

    close(clifd);
}

int main(int argc, char const *argv[])
{
    //创建套接字
    int serverfd = socket(AF_INET, SOCK_STREAM, 0);
    if (serverfd < 0)
    {
        perror("socket err");
        return -1;
    }

    //绑定自己的地址
    struct sockaddr_in myaddr;
    socklen_t addrlen = sizeof(myaddr);

    memset(&myaddr, 0, addrlen);
    myaddr.sin_family = AF_INET;
    myaddr.sin_port = htons(8888);
#if 0    
    myaddr.sin_addr.s_addr = inet_addr("192.168.51.193");
#else
    myaddr.sin_addr.s_addr = inet_addr("192.168.124.128");
#endif
    int ret = bind(serverfd, (struct sockaddr *)&myaddr, addrlen);
    if (ret < 0)
    {
        perror("bind err");
        return -1;
    }

    //启动监听
    ret = listen(serverfd, 5);
    if (ret < 0)
    {
        perror("bind err");
        return -1;
    }

    while (1)
    {
        //接收客户端的连接
        //定义代表客户端的结构体变量
        struct sockaddr_in cliaddr;
        int clifd = accept(serverfd, (struct sockaddr *)&cliaddr, &addrlen);
        if (clifd < 0)
        {
            perror("accept err");
            return -1;
        }
        printf("last\n");
        printf("新的连接过来了 = %d\n", clifd);

        //创建一个线程，来处理新的客户端连接
        pthread_t tid;
        pthread_create(&tid, NULL, func, &clifd);
        pthread_t tid2;
        pthread_create(&tid, NULL, func2, &clifd);
    }

    close(serverfd);

    return 0;
}